package com.mmall.controller.task;

import com.mmall.common.Const;
import com.mmall.common.RedisShardedPool;
import com.mmall.controller.common.RedissonManager;
import com.mmall.service.IOrderService;
import com.mmall.util.DateTimeUtil;
import com.mmall.util.PropertiesUtil;
import com.mmall.util.RedisShardedPoolUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class CloseOrderTask {
    @Autowired
    private IOrderService iOrderService;

    @Autowired
    private RedissonManager redissonManager;

    //@Scheduled(cron = "0 */1 * * * ?")//每分钟执行一次
   /* public void closeOrderV1() {
        log.info("关闭订单定时任务启动,时间:{}", DateTimeUtil.dateToStr(new Date()));
        Integer hour = Integer.parseInt(PropertiesUtil.getProperty("closeOrderTimeHour"));
        iOrderService.closeOrder(hour);

        log.info("关闭订单定时任务结束,时间:{}", DateTimeUtil.dateToStr(new Date()));

    }*/

    //   @Scheduled(cron = "0 */1 * * * ?")//每分钟执行一次
/*    public void closeOrderV2() {
        log.info("关闭订单定时任务启动,时间:{}", DateTimeUtil.dateToStr(new Date()));
        //分布式锁时间
        Integer locktimeOut = Integer.parseInt(PropertiesUtil.getProperty("lockTime"));
        Long setNxResult = RedisShardedPoolUtil.setNx(Const.REDIS_LOCKE_TASK_CLOSE, String.valueOf(System.currentTimeMillis() + locktimeOut));

        if (setNxResult != null && setNxResult.intValue() == 1) {
            this.closeOrder(Const.REDIS_LOCKE_TASK_CLOSE);
        } else {
            //没有获取到分布式锁
            log.info("没有获取到锁:{}", Const.REDIS_LOCKE_TASK_CLOSE);
        }


        log.info("关闭订单定时任务结束,时间:{}", DateTimeUtil.dateToStr(new Date()));

    }*/

    // @Scheduled(cron = "0 */1 * * * ?")//每分钟执行一次
/*
    public void closeOrderV3() {

        log.info("关闭订单定时任务启动,时间:{}", DateTimeUtil.dateToStr(new Date()));
        //分布式锁时间
        Integer locktimeOut = Integer.parseInt(PropertiesUtil.getProperty("lockTime"));
        Long setNxResult = RedisShardedPoolUtil.setNx(Const.REDIS_LOCKE_TASK_CLOSE, String.valueOf(System.currentTimeMillis() + locktimeOut));

        if (setNxResult != null && setNxResult.intValue() == 1) {
            this.closeOrder(Const.REDIS_LOCKE_TASK_CLOSE);
        } else {
            //没有获取到分布式锁

            log.info("第一次没有获取到锁:{}", Const.REDIS_LOCKE_TASK_CLOSE);

            String lockVal = RedisShardedPoolUtil.get(Const.REDIS_LOCKE_TASK_CLOSE);
            if ((lockVal != null) && (System.currentTimeMillis() > Long.parseLong(lockVal))) {
                String getSetResult = RedisShardedPoolUtil.getSet(Const.REDIS_LOCKE_TASK_CLOSE, String.valueOf(System.currentTimeMillis() + locktimeOut));

                if (getSetResult == null || (StringUtils.equals(getSetResult, lockVal))) {
                    //真正获取到锁
                    this.closeOrder(Const.REDIS_LOCKE_TASK_CLOSE);
                } else {

                    log.info("第三次没有获取到锁:{}", Const.REDIS_LOCKE_TASK_CLOSE);
                }

            } else {

                log.info("第二次没有获取到锁:{}", Const.REDIS_LOCKE_TASK_CLOSE);
            }


        }


        log.info("关闭订单定时任务结束,时间:{}", DateTimeUtil.dateToStr(new Date()));
    }
*/


    @Scheduled(cron = "0 */1 * * * ?")//每分钟执行一次
    public void closeOrderV4() {
        boolean getLock = false;
        //设置锁名字
        RLock rLock = redissonManager.getRedisson().getLock(Const.REDIS_LOCKE_TASK_CLOSE);

        //尝试获取锁
        try {
            if (getLock = rLock.tryLock(0, 5, TimeUnit.SECONDS)) {

                log.info("redisson锁获取结果:{},线程名称:{}", getLock, Thread.currentThread().getName());

                Integer hour = Integer.parseInt(PropertiesUtil.getProperty("closeOrderTimeHour"));
                iOrderService.closeOrder(hour);
            } else {
                log.info("redisson锁获取结果:{},线程名称:{}", getLock, Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
            log.info("redisson锁获取结果:{},线程名称:{},异常情况:{}", getLock, Thread.currentThread().getName(), e);
        } finally {
            if (!getLock) {
                return;
            }
            rLock.unlock();
            log.info("释放redisson锁");
        }
    }


    private void closeOrder(String lockName) {
        RedisShardedPoolUtil.exPire(lockName, Integer.parseInt(PropertiesUtil.getProperty("lockTime"))); //重置有效期
        try {
            log.info("获取锁:{},线程名称:{}", lockName, Thread.currentThread().getName());
            Integer hour = Integer.parseInt(PropertiesUtil.getProperty("closeOrderTimeHour"));
            iOrderService.closeOrder(hour);

        } catch (Exception e) {
            log.info("执行关单异常:{}", e);
        } finally {
            RedisShardedPoolUtil.del(lockName);
            log.info("释放锁:{},线程名称:{}", lockName, Thread.currentThread().getName());

        }


    }
}
